#include "SemanticNodeSimulation.h"

#include "SemanticNodeExpression.h"
#include "main2.h"

/*
<simulation>	~	simulation NAME { <simulation_body> }
<simulation_body>	~	<simulation_stmt> <simulation_body>
<simulation_body>	~
<simulation_stmt>	~	<sim_configuration>
<simulation_stmt>	~	<sim_run>
<simulation_stmt>	~	<sim_clear>
<simulation_stmt>	~	<sim_reset>
<sim_configuration>	~	configuration <name> ( <arguments> ) ;

<sim_run>	~	run <expression> simulations <upto_expression>	;
<sim_run>	~	run <upto_expression>	;

<sim_clear>	~	clear ;
<sim_reset>	~	reset ;
*/

SemanticNodeSimulation::SemanticNodeSimulation(const SyntaxTreeNode *syntaxNode, SemanticNode *parent):SemanticNode(parent){
	LexicUnit lu = CompilerData->Units->GetLexicUnit(syntaxNode->Nodes->GetData(1)->LexUnitID);
	name = CompilerData->Units->GetLexicUnitString(&lu);
	SyntaxTreeNode *simulationBody = syntaxNode->Nodes->GetData(3);
	for (int i = 0; i < simulationBody->Nodes->GetCount(); i++){
		switch (simulationBody->Nodes->GetData(i)->Production){
		case Gr_SimulationStmt__SimConfiguration:
			semanticStmts.push_back(new SemanticNodeSimConfiguration(simulationBody->Nodes->GetData(i)->Nodes->GetData(0), this));
			break;
		case Gr_SimulationStmt__SimRun:
			semanticStmts.push_back(new SemanticNodeSimRun(simulationBody->Nodes->GetData(i)->Nodes->GetData(0), this));
			break;
		case Gr_SimulationStmt__SimReset:
			semanticStmts.push_back(new SemanticNodeSimReset(simulationBody->Nodes->GetData(i)->Nodes->GetData(0), this));
			break;
		case Gr_SimulationStmt__SimClear:
			semanticStmts.push_back(new SemanticNodeSimClear(simulationBody->Nodes->GetData(i)->Nodes->GetData(0), this));
			break;
		default:
			cout << "greska simulation node" << endl;
		}
	}

}

SemanticNodeSimulation::~SemanticNodeSimulation(){
}

std::string SemanticNodeSimulation::toDebugString(int tab){
	std::ostringstream res;
	for (int i = 0; i < tab; i++) res << DEBUG_STRING_RAZMAK;
	res << "simulation " << name << endl;
	for (std::vector<SemanticNode *>::iterator i = semanticStmts.begin(); i != semanticStmts.end(); ++i)
		res << (*i)->toDebugString(tab + 1);
	return res.str();
}

SemanticNodeSimConfiguration::SemanticNodeSimConfiguration(const SyntaxTreeNode * syntaxNode, SemanticNode *parent):SemanticNode(parent){
	name = flattenNamePeriodAdd(*syntaxNode->Nodes->GetData(1));
	arguments = OurSemanticAnalyzer::analyzeNodeArgument(syntaxNode->Nodes->GetData(3), this);
}

SemanticNodeSimConfiguration::~SemanticNodeSimConfiguration(){
}

std::string SemanticNodeSimConfiguration::toDebugString(int tab){
	std::ostringstream res;
	for (int i = 0; i < tab; i++) res << DEBUG_STRING_RAZMAK;
	res << "configuration " << name << endl;
	for (int i = 0; i < tab+1; i++) res << DEBUG_STRING_RAZMAK;
	res << "parameters:" << endl;
	for (std::vector<SemanticNodeExpression *>::iterator i = arguments.begin(); i != arguments.end(); ++i)
		res << (*i)->toDebugString(tab + 1);
	return res.str();
}

SemanticNodeSimRun::SemanticNodeSimRun(const SyntaxTreeNode * syntaxNode, SemanticNode *parent):SemanticNode(parent){
	switch (syntaxNode->Production){
	case Gr_SimRun__run_Expression_simulations_UptoExpression_spSemiCol:
		expression = new SemanticNodeExpression(syntaxNode->Nodes->GetData(1), this);
		if (syntaxNode->Nodes->GetData(3)->Production == Gr_UptoExpression__upto_Expression)
			uptoExpression = new SemanticNodeExpression(syntaxNode->Nodes->GetData(3)->Nodes->GetData(1), this);
		else
			uptoExpression = NULL;
		break;
	case Gr_SimRun__run_UptoExpression_spSemiCol:
		expression = NULL;
		if (syntaxNode->Nodes->GetData(1)->Production == Gr_UptoExpression__upto_Expression)
			uptoExpression = new SemanticNodeExpression(syntaxNode->Nodes->GetData(1)->Nodes->GetData(1), this);
		else
			uptoExpression = NULL;
		break;
	default:
		break;// ne smije se dogoditi
	}

}

SemanticNodeSimRun::~SemanticNodeSimRun(){
	delete expression;
	expression = NULL;
	delete uptoExpression;
	uptoExpression = NULL;
}

std::string SemanticNodeSimRun::toDebugString(int tab){
	std::ostringstream res;
	for (int i = 0; i < tab; i++) res << DEBUG_STRING_RAZMAK;
	res << "run" << endl;
	for (int i = 0; i < tab; i++) res << DEBUG_STRING_RAZMAK;

	if (expression){
		res << "run" << endl << expression->toDebugString(tab+1);
		if(uptoExpression)
		{
			for (int i = 0; i < tab; i++) res << DEBUG_STRING_RAZMAK;
			res << "simulations upto" << uptoExpression->toDebugString(tab+1);
		}
	} else {
		res << "run" << endl;
		if(uptoExpression)
			res << uptoExpression->toDebugString(tab+1);
	}
	return res.str();
}

SemanticNodeSimReset::SemanticNodeSimReset(const SyntaxTreeNode * syntaxNode, SemanticNode *parent):SemanticNode(parent)
{
}

SemanticNodeSimReset::~SemanticNodeSimReset()
{
}

std::string SemanticNodeSimReset::toDebugString(int tab)
{
	std::ostringstream res;
	for (int i = 0; i < tab; i++) res << DEBUG_STRING_RAZMAK;
	res << "reset" << endl;
	return res.str();
}

SemanticNodeSimClear::SemanticNodeSimClear(const SyntaxTreeNode * syntaxNode, SemanticNode *parent):SemanticNode(parent)
{
}

SemanticNodeSimClear::~SemanticNodeSimClear()
{
}

std::string SemanticNodeSimClear::toDebugString(int tab){
	std::ostringstream res;
	for (int i = 0; i < tab; i++) res << DEBUG_STRING_RAZMAK;
	res << "clear" << endl;
	return res.str();
}
